﻿//using System;
//using System.Collections.Generic;
//using System.Linq;
//using Microsoft.Xna.Framework;
//using Microsoft.Xna.Framework.GamerServices;
//using Microsoft.Xna.Framework.Graphics;
//using Microsoft.Xna.Framework.Input;

//namespace X3DXamlXna
//{

//    public struct Camera
//    {
//        private Matrix view;
//        public Matrix View { get { return view; } set { view = value; } }
//        private Matrix projection;
//        public Matrix Projection { get { return projection; } set { projection = value; } }
//        public string Name { get; set; }
//        public float FieldOfView { get; set; }


//        public override bool Equals(object obj)
//        {
//            if (obj == null)
//                throw new NullReferenceException();
//            if (!(obj is Camera))
//            {
//                return false;
//            }
//            Camera tmp = (Camera) obj;
//            return
//                this.Name != null &&
//                tmp.Name != null &&
//                this.FieldOfView == tmp.FieldOfView &&
//                this.Name.Equals(tmp.Name) &&
//                this.Projection.Equals(tmp.Projection) &&
//                this.View.Equals(tmp.View);
//        }

//        public bool isInitialized()
//        {
//            return
//                FieldOfView != 0 &&
//                Name != null;
//        }
//    }

//    public interface ICameraService
//    {
//        void AddViewPoint(Camera camera);
//        IEnumerable<Camera> ViewPoints { get; set; }
//        Matrix View { get; }
//        Matrix Projection { get; }
//        Vector3 Eye { get; }
//        Camera CurrentCamera { get; }

//        BoundingFrustum myBoundingFrustum { get; set; }
//    }

    

//    public class CameraManager : Microsoft.Xna.Framework.GameComponent, ICameraService
//    {
//        public Camera CurrentCamera { get { return movingCamera; } private set { } }
//        public IEnumerable<Camera> ViewPoints { get { return viewPoints as IEnumerable<Camera>; } set { } }
//        public Matrix View { get { return movingCamera.View; } private set { movingCamera.View = value; } }
//        public Matrix Projection { get { return movingCamera.Projection; } private set { movingCamera.Projection = value; } }
//        public string Name { get { return movingCamera.Name; } private set { } }

//        public BoundingFrustum myBoundingFrustum { get; set; }

//        private Camera defaultCamera;
//        private Camera movingCamera;
//        public LinkedListNode<Camera> viewpointIterator { get; set; }
//        private LinkedList<Camera> viewPoints = new LinkedList<Camera>();
//        private float moovingSpeed = 20;
//        public Vector3 Eye { get { return Vector3.Transform(-View.Translation, Matrix.Transpose(View)); } private set { } }

//        private Cinematic cinematic = new Cinematic();

//        private KeyboardState old;

//        public CameraManager(Game game)
//            : base(game)
//        {
//            game.Services.AddService(typeof(ICameraService), this);

//        }

//        public override void Initialize()
//        {
//            // TODO: Add your initialization code here
//            defaultCamera = new Camera()
//            {
//                Name = "DefaultCamera",
//                View = Matrix.CreateLookAt(new Vector3(0f, 0f, 0f), -Vector3.UnitZ, Vector3.Up),
//                Projection = Matrix.CreatePerspectiveFieldOfView(MathHelper.PiOver4, Game.GraphicsDevice.Viewport.AspectRatio, Consts.NEAR_PLANE, Consts.FAR_PLANE),
//                FieldOfView = MathHelper.PiOver4,
//            };
//            movingCamera = defaultCamera;
//            myBoundingFrustum = new BoundingFrustum(View * Projection);
//            base.Initialize();
//        }

//        /// <summary>
//        /// Allows the game component to update itself.
//        /// </summary>
//        public override void Update(GameTime gameTime)
//        {
//            // TODO: Add your update code here

//            //ProcessImput(gameTime);

//            if (cinematic.isActive())
//            {
//                var tmp = cinematic.Next(gameTime);
//                movingCamera = tmp;
//                ProcessNecessaryInput();
//            }
//            else
//            {
//                if (cinematic.WhereIAM.Name != null)
//                    cinematic = new Cinematic();
//                ProcessInput(gameTime);
//                ProcessNecessaryInput();
//            }

//            myBoundingFrustum = new BoundingFrustum(View * Projection);
//            base.Update(gameTime);
//        }

        
//        private void ProcessInput(GameTime gameTime)
//        {
//            float dt = .9f * gameTime.ElapsedGameTime.Milliseconds / 1000 * moovingSpeed;
//            float dr = 0.12f * gameTime.ElapsedGameTime.Milliseconds / 1000;


//            var keys = Keyboard.GetState().GetPressedKeys();


//            foreach (var key in keys)
//            {

//                switch (key)
//                {
//                    case Keys.W:
//                        movingCamera.Name = "UserCamera";
//                        movingCamera.View *= Matrix.CreateTranslation(Vector3.Backward * dt);
//                        break;
//                    case Keys.S:
//                        movingCamera.Name = "UserCamera";
//                        movingCamera.View *= Matrix.CreateTranslation(Vector3.Forward * dt);
//                        break;
//                    case Keys.D:
//                        movingCamera.Name = "UserCamera";
//                        movingCamera.View *= Matrix.CreateTranslation(Vector3.Left * dt);
//                        break;
//                    case Keys.A:
//                        movingCamera.Name = "UserCamera";
//                        movingCamera.View *= Matrix.CreateTranslation(Vector3.Right * dt);
//                        break;
//                    case Keys.Space:
//                        movingCamera.Name = "UserCamera";
//                        movingCamera.View *= Matrix.CreateTranslation(Vector3.Down * dt);
//                        break;
//                    case Keys.X:
//                        movingCamera.Name = "UserCamera";
//                        movingCamera.View *= Matrix.CreateTranslation(Vector3.Up * dt);
//                        break;
//                    case Keys.Up:
//                        movingCamera.Name = "UserCamera";
//                        movingCamera.View *= Matrix.CreateFromYawPitchRoll(0, (float)Math.PI * dr, 0);
//                        break;
//                    case Keys.Down:
//                        movingCamera.Name = "UserCamera";
//                        movingCamera.View *= Matrix.CreateFromYawPitchRoll(0, -(float)Math.PI * dr, 0);
//                        break;
//                    case Keys.LeftAlt:
//                        movingCamera.Name = "UserCamera";
//                        movingCamera.View *= Matrix.CreateFromYawPitchRoll(0, 0, (float)Math.PI * dr);
//                        break;
//                    case Keys.LeftControl:
//                        movingCamera.Name = "UserCamera";
//                        movingCamera.View *= Matrix.CreateFromYawPitchRoll(0, 0, -(float)Math.PI * dr);
//                        break;
//                    case Keys.Left:
//                        movingCamera.Name = "UserCamera";
//                        movingCamera.View *= Matrix.CreateFromYawPitchRoll(-(float)Math.PI * dr, 0, 0);
//                        break;
//                    case Keys.Right:
//                        movingCamera.Name = "UserCamera";
//                        movingCamera.View *= Matrix.CreateFromYawPitchRoll((float)Math.PI * dr, 0, 0);
//                        break;
//                    case Keys.RightControl:
//                        if (moovingSpeed >= 5)
//                            moovingSpeed -= 3.333f;
//                        break;
//                    case Keys.RightShift:
//                        if (moovingSpeed <= 400)
//                            moovingSpeed += 3.333f;
//                        break;
//                    default: break;
//                }
//            }

            
//        }

//        private void ProcessNecessaryInput()
//        {
//            var now = Keyboard.GetState();
//            if (now.IsKeyDown(Keys.PageUp))
//            {
//                if (!old.IsKeyDown(Keys.PageUp))
//                {
//                    if (viewPoints.Count == 0)
//                    {
//                        cinematic = new Cinematic(movingCamera, defaultCamera, Game.GraphicsDevice.Viewport.AspectRatio);
//                    }
//                    else
//                    {
//                        if (viewpointIterator.Next == null)
//                        {
//                            viewpointIterator = viewPoints.First;
//                        }
//                        else
//                        {
//                            viewpointIterator = viewpointIterator.Next;
//                        }
//                        cinematic = new Cinematic(movingCamera, viewpointIterator.Value, Game.GraphicsDevice.Viewport.AspectRatio);
//                    }
//                }
//            }
            
//            if (now.IsKeyDown(Keys.PageDown))
//            {
//                if (!old.IsKeyDown(Keys.PageDown))
//                {
//                    if (viewPoints.Count == 0)
//                    {
//                        cinematic = new Cinematic(movingCamera, defaultCamera, Game.GraphicsDevice.Viewport.AspectRatio);
//                    }
//                    else
//                    {
//                        if (viewpointIterator.Previous == null)
//                        {
//                            viewpointIterator = viewPoints.Last;
//                        }
//                        else
//                        {
//                            viewpointIterator = viewpointIterator.Previous;
//                        }
//                        cinematic = new Cinematic(movingCamera, viewpointIterator.Value, Game.GraphicsDevice.Viewport.AspectRatio);
//                    }


                    
//                }
//            }

//            if (now.IsKeyDown(Keys.Escape))
//            {
//                movingCamera.Name = "UserCamera";
//                cinematic.Stop();

//            }

//            old = now;

//        }

//        public void AddViewPoint(Camera camera)
//        {
//            viewPoints.AddLast(camera);
//            if (viewpointIterator == null)
//            {
//                viewpointIterator = viewPoints.First;
//                movingCamera = viewpointIterator.Value;
//            }
//        }

        
//    }
//    class Cinematic
//    {
//        private const float CINEMATIC_TIME = 3;

//        private float cinematicPassed;
//        private Vector3 fromEye;
//        private Vector3 toEye;
//        private Quaternion fromQuat;
//        private Quaternion toQuat;

//        private float fromField;
//        private float toField;
//        private Camera whereToGo;
//        private Camera whereIAm;
//        public Camera WhereIAM { get { return whereIAm; } private set { } }
//        private float aspectRatio;

//        public Cinematic()
//        {
//            cinematicPassed = -1;
//        }

//        public Cinematic(Camera from, Camera to, float Ratio)
//        {
//            whereIAm = from;
//            whereToGo = to;
//            aspectRatio = Ratio;
//            this.stimate();
//        }

//        public Camera Next(GameTime gameTime)
//        {
//            if (cinematicPassed >= CINEMATIC_TIME)
//            {
//                whereIAm = whereToGo;
//            }
//            else
//            {
//                var dt = gameTime.ElapsedGameTime.Milliseconds / 1000f;
//                cinematicPassed += dt;

//                var currentEye = Vector3.SmoothStep(fromEye, toEye, cinematicPassed / CINEMATIC_TIME);

//                var tmp = Matrix.Transform(Matrix.Identity, Quaternion.Slerp(fromQuat, toQuat, cinematicPassed / CINEMATIC_TIME));
//                tmp *= Matrix.CreateTranslation(currentEye);


//                whereIAm.View = Matrix.CreateLookAt(currentEye, tmp.Translation + tmp.Forward, tmp.Up);

//                //whereIAm.FieldOfView = MathHelper.Lerp(fromField, toField, cinematicPassed / CINEMATIC_TIME);
//                //whereIAm.Projection = Matrix.CreatePerspectiveFieldOfView(MathHelper.Lerp(fromField, toField, cinematicPassed / CINEMATIC_TIME), aspectRatio, 0.1f, 2000f);

//            }
//            return whereIAm;
//        }

//        public bool isActive()
//        {
//            return
//                whereIAm.isInitialized() &&
//                whereToGo.isInitialized() &&
//                !whereIAm.Equals(whereToGo);
//        }

//        private void stimate()
//        {

//            cinematicPassed = 0;

//            fromEye = Vector3.Transform(-whereIAm.View.Translation, Matrix.Transpose(whereIAm.View));
//            toEye = Vector3.Transform(-whereToGo.View.Translation, Matrix.Transpose(whereToGo.View));

//            var c = whereIAm.View * Matrix.CreateTranslation(-whereIAm.View.Translation);
//            var toRot = whereToGo.View * Matrix.CreateTranslation(-whereToGo.View.Translation);

//            Vector3 a, b;
//            Matrix.Transpose(c).Decompose(out a, out fromQuat, out b);
//            Matrix.Transpose(toRot).Decompose(out a, out toQuat, out b);

//            fromField = whereIAm.FieldOfView;
//            toField = whereToGo.FieldOfView;

//            whereIAm.Name = "Moving to " + whereToGo.Name;
//        }

//        public void Stop()
//        {
//            whereToGo = whereIAm;
//        }

//    }
//}
